package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.Border;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;

import main.Conference;
import main.Manuscript;
import main.Review;
import main.User;


//TODO leave check mark in check box after a review is uploaded
//or grey-out buttons afterwards
//(otherwise it is unclear what pressing download will do)
/**
 * ReviewSubmitsFrame
 * 
 * @author Daniel Anderson - GUI Functionality
 * @author Amandeep - Base GUI design
 * @author Holly - JTable and JTable Button Solution from PCViewsFrame
 * @author Cristopher - GetFileBody from AuthorSubmitsFrame
 * @version 12/3
 */
public class ReviewSubmitsFrame extends JFrame{

	private static final long serialVersionUID = 1L;

	private final JFileChooser my_file_chooser = new JFileChooser();
	
	//GUI Stuff
	private JFrame my_frame;
	private JTextField my_text_field;
	private JTable my_table;
	private JPanel my_manu_panel;
	private JPanel my_review_panel;
	private JPanel my_button_panel;
	
	//Data Stuff
	private User my_user;
	private Conference my_conference;
	private Manuscript my_selected_manuscript;
	private File my_selected_file;
	

	/**
	 * Constructor for ReviewSubmitsFrame
	 * @param the_user is the current user selected.
	 * @param the_conf is the current conference selected.
	 */
	public ReviewSubmitsFrame(User the_user, Conference the_conf) {
		my_frame = new JFrame("Manuview -- Review Submission");
		my_manu_panel = new JPanel();
		my_review_panel = new JPanel();
		my_button_panel = new JPanel(new GridBagLayout());
		my_text_field = new JTextField("No File Selected");
		my_user = the_user;
		my_conference = the_conf;
	    my_file_chooser.setFileFilter(new FileNameExtensionFilter("Text Files", "txt"));
	    generateTable();//This initializes my_table
	}//end of Constructor
	
	/**
	 * This starts the GUI
	 */
	public void start() {
		//Setup
		my_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Border blackborder = BorderFactory.createLineBorder(Color.BLACK);
		my_manu_panel.setBorder(blackborder);// unsubmit
		my_review_panel.setBorder(blackborder);// Where the titles are
		my_button_panel.setBorder(blackborder);// bottom upload area
		my_frame.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		//Add the JTable Panel
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(1,2,1,2);
	    c.gridx = 0;
	    c.weightx = 1;
	    c.weighty = 2;
	    c.gridy = 1;
	    my_frame.add(my_manu_panel, c);
		
	    //Add the bottom button panel
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(2,2,2,1);
		c.gridwidth = 2;
		c.weightx = 2;
		c.weighty = .5;
	    c.gridx = 0;
	    c.gridy = 2;
	    my_frame.add(my_button_panel, c);

	    //Add the JTable to the new ScrollWindow
		JScrollPane scrolltable = new JScrollPane(my_table);
		scrolltable.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrolltable.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		my_manu_panel.add(scrolltable, BorderLayout.CENTER);
	    
		// Setup bottom Button Panel components
		//JTextField textField = new JTextField();
		final JButton uploadButton = new JButton("UPLOAD");
		uploadButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String text = my_text_field.getText();
				if(!text.substring(text.length() - 4).equals(".txt")) {
					JOptionPane.showMessageDialog(null, "File not .txt format!");
					return;
				}
				my_selected_file = new File(text);
				String titlename = my_selected_file.getName();
				titlename = titlename.substring(0, titlename.length()-4);		
				try {
					Review rev = new Review(titlename, my_user.getName(), 
							my_user.getID(), getFileBody());
					if(!my_selected_manuscript.getReviews().contains(rev)) {
						my_conference.addReview(my_selected_manuscript, rev);
					} else {
						int index = my_selected_manuscript.getReviews().indexOf(rev);
						my_conference.updateReview(my_selected_manuscript, 
								my_selected_manuscript.getReviews().get(index), rev);
					}
				} catch (FileNotFoundException e1) {
					JOptionPane.showMessageDialog(null, "Invalid File!");
				}
				refreshJTable();
				JOptionPane.showMessageDialog(null, "Upload Complete!");
			}
		});
		final JButton downloadButton = new JButton("DOWNLOAD");
		downloadButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					File newfile = new File(my_selected_manuscript.getTitle() + ".txt");
					FileWriter f = new FileWriter(newfile);
					f.write(my_selected_manuscript.getText());
					f.close();
					JOptionPane.showMessageDialog(null, "File Downloaded!");
				} catch(IOException ex) {
					//ex.printStackTrace();
					JOptionPane.showMessageDialog(null, "File Download Failed!");
				}
			}
		});
		GridBagConstraints gbc2 = new GridBagConstraints();
		JLabel uploadPanelLabel = new JLabel("UPLOAD NEW REVIEW");
		final JButton chooseButton = new JButton("CHOOSE...");
		chooseButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				File file = doChoose();
				my_text_field.setText(file.getPath());
			}
		});
		final JButton cancelButton = new JButton("CANCEL");
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				my_text_field.setText("No File Selected");
			}
		});
		
		
		final JButton closeButton = new JButton("CLOSE");
		closeButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				my_conference.save();
				StartFrame back = new StartFrame();
				back.start();
				my_frame.dispose();
			}
		});
		
		uploadButton.setEnabled(false);
		downloadButton.setEnabled(false);

		
		// adds the label
		gbc2.fill = GridBagConstraints.HORIZONTAL;
		gbc2.gridx = 1;
		gbc2.gridy = 0;
		gbc2.weightx = 1;
		gbc2.gridheight = 2;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(uploadPanelLabel, gbc2);
		// adds the choose button
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 0;
		gbc2.gridy = 2;
		gbc2.weightx = .5;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(chooseButton, gbc2);
		// adds the textfield
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 1;
		gbc2.gridy = 2;
		gbc2.weightx = 1;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(my_text_field, gbc2);
		// adds the upload button
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 3;
		gbc2.gridy = 2;
		gbc2.weightx = 1;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(uploadButton, gbc2);
		//adds the download button
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 5;
		gbc2.gridy = 2;
		gbc2.weightx = 1;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(downloadButton, gbc2);
		// adds the cancel button
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 3;
		gbc2.gridy = 4;
		gbc2.weightx = 1;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(cancelButton, gbc2);
		// adds the close button
		gbc2.fill = GridBagConstraints.BOTH;
		gbc2.gridx = 5;
		gbc2.gridy = 4;
		gbc2.weightx = 1;
		gbc2.insets = new Insets(0,1,1,1);
		my_button_panel.add(closeButton, gbc2);
		
		my_frame.pack();
		my_frame.setSize(600,600);
		my_frame.setVisible(true);
	}//end of start
	
	/**
	 * Holly 12/1 Initializes my_table
	 */
	@SuppressWarnings("serial")
	private void generateTable() {
		//JTable prep
		String[] colNames = {"Author", "Paper", "Status"};
		Object[][] tableData = new Object[my_conference.getManuscriptsForReviewer(my_user).size()][3];
		setTableData(tableData);
		ManuTableModel dataModel= new ManuTableModel(tableData, colNames);
		my_table = new JTable(dataModel){
			public boolean isCellEditable(int rowIndex, int colIndex) {
				return false; //Disallow the editing of any cell
			}
		};
		my_table.addMouseListener(new TblMouseListener(my_table));
		my_table.setRowSorter(new TableRowSorter<ManuTableModel>(dataModel));
		my_table.setFillsViewportHeight(true);
		my_table.setCellSelectionEnabled(true);
		my_table.setShowGrid(true);
		my_table.setGridColor(Color.DARK_GRAY);
		my_table.setRowHeight(50);
		my_table.getTableHeader().setPreferredSize(new Dimension(my_table.getTableHeader().getWidth(),50));
		//table.setCellSelectionEnabled(false);
		my_table.setSelectionBackground(my_table.getBackground());
		my_table.setSelectionForeground(my_table.getForeground());
		TableColumn col = my_table.getColumnModel().getColumn(0);
		col.setCellRenderer(new TableCkBox());
	}//end generateTable
	
	/**
	 * @author Holly 12/2 -- "refreshes" the JTable
	 */
	private void refreshJTable(){
		String[] colNames = {"Author", "Paper", "Status"};
		Object[][] tableData = 
			new Object[my_conference.getManuscriptsForReviewer(my_user).size()][3];
		setTableData(tableData);
		ManuTableModel dataModel= new ManuTableModel(tableData, colNames);
		my_table.setModel(dataModel);
		//changing the model makes it necessary to re-add the cell renderer
		TableColumn col = my_table.getColumnModel().getColumn(0);
		col.setCellRenderer(new TableCkBox());
	}//end refreshJTable
	
	/**
	 * @author Holly 12/1 -- prepares the manuscript and review data for display
	 */
	private void setTableData(Object[][] dataArray) {
		ArrayList<Manuscript> reviewerManuList = 
			my_conference.getManuscriptsForReviewer(my_user);	
		for (int i=0; i< reviewerManuList.size(); i++){
			Manuscript man = reviewerManuList.get(i);
			TableCkBox ckBox = new TableCkBox(man.getAuthor());
			ckBox.addActionListener(new CkBoxListener(man, ckBox));
			dataArray[i][0] = ckBox;
			dataArray[i][1] = man.getTitle();
		//check to see if this user/reviewer has submitted a review for manuscript
			String revStatus = "Not Reviewed";
			for (Review rev : man.getReviews()){
				if (rev.getAuthorID().equals(my_user.getID())){
					revStatus = "Reviewed";
				}
			}
			dataArray[i][2] = revStatus;	
		}
	}//end of setTableData
	
	//Copied from AuthorSubmitsFrame
	/**
	 * A FileChooser dialog appears asking for a text file.
	 * @return The selected File Object
	 */
	private File doChoose() {
		final int result = my_file_chooser.showOpenDialog(null);
		File textFile = new File("No File Selected");
		if (result == JFileChooser.APPROVE_OPTION){
			textFile = my_file_chooser.getSelectedFile();
			JOptionPane.showMessageDialog(null, "File Selected!");
		}
		else if (result == JFileChooser.CANCEL_OPTION) {
			JOptionPane.showMessageDialog(null, "Action Cancelled");
	    }
		return textFile;
	}//end of ChooseFile
	
	/**
	 * Collects the data in a file as one long string.
	 * 
	 * @author Cristopher
	 * @return the string representation of the file
	 * @throws FileNotFoundException if my_selected_file is not found
	 */
	private String getFileBody() throws FileNotFoundException {
		Scanner read = new Scanner(new FileReader(my_selected_file));
		StringBuilder body = new StringBuilder();
		try {
			while (read.hasNextLine()) {
				body.append(read.nextLine());
			}
		} finally {
			read.close();
		}
		return body.toString();
	}// end of getBody
	
	/////////////////////////////////////////////////////////////
	//////////////*Inner Classes for JTable*/////////////////////
	/////////////////////////////////////////////////////////////
	
	@SuppressWarnings("serial")
	/**@author Holly 12/1 -This class sets the specifications for the JTable model*/
	class ManuTableModel extends DefaultTableModel {
		private Object data[][];
		
		public ManuTableModel(Object[][] dataArr, String[] colNames){
			super(dataArr, colNames);
			data=dataArr;
		}
		//this method is used to get the button object out of the JTable for event handling
		@Override
		public Object getValueAt(int row, int col) {
	        return data[row][col];
	    }
		
		@Override
		 public Class getColumnClass(int c) {
		        return getValueAt(0, c).getClass();
		    }

		@Override
		public boolean isCellEditable(int row, int col){
			return false;
		}
		
		
	}//end of ManuTableModel class
	
	/**
	 * @author Holly 12/1
	 * This class is necessary to render the manuscript check box
	 * for display within the table.
	 */
	@SuppressWarnings("serial")
	class TableCkBox extends JCheckBox implements TableCellRenderer{
		public TableCkBox(){
			super();
		}
		
		public TableCkBox(String auth_name){
			super(auth_name);
		}
		
		@Override
		public Component getTableCellRendererComponent(JTable table,Object value, 
													boolean selected, boolean hasFocus, 
													int row,int column) {
			
			this.setText(((TableCkBox)value).getText());
			this.addActionListener(((TableCkBox)value).getActionListeners()[0]);
			this.setBackground(Color.WHITE);
			this.setEnabled(true);
			if (selected){
				this.setSelected(true);
			} else {
				this.setSelected(false);
			}
			return this;	
		}
		
	} //end of TableCkBox class
	
	/**
	 * @author Holly 12/1
	 * This MouseListener class is necessary for recognizing clicks on the
	 * manuscript check box and activating its assigned actionlistener 
	 */
	private class TblMouseListener implements MouseListener{
		JTable table;
		
		public TblMouseListener(JTable aTable){
			table=aTable;
		}

		@Override
		public void mouseClicked(MouseEvent e) {
			//see if the mouse was over a button when this happened,
			//if so, get the value of that cell, type cast to TblCkBox and call doClick
			int row = table.rowAtPoint(e.getPoint());
		    int col = table.columnAtPoint(e.getPoint());
		    if (col == 0) {
		    	TableCkBox ckBox = (TableCkBox) table.getValueAt(row, col);
		    	ckBox.doClick();
		    }
		    table.repaint();
		}

		@Override //do nothing
		public void mousePressed(MouseEvent e) { }

		@Override //do nothing
		public void mouseReleased(MouseEvent e) { }

		@Override //do nothing
		public void mouseEntered(MouseEvent e) { }

		@Override //do nothing
		public void mouseExited(MouseEvent e) {	}		
	}//end of TblMouseListener class
	
	/**
	 * @author Holly 12/1
	 * This class holds a manuscript object for assigning to my_selected_manuscript 
	 */
	private class CkBoxListener implements ActionListener{
		Manuscript my_manu;
		
		//TODO remove this?
		TableCkBox my_ckbox;
		
		public CkBoxListener(Manuscript a_manuscript, TableCkBox a_ckbox){
			my_manu = a_manuscript;	
			my_ckbox = a_ckbox;
		}
		
		@Override
		public void actionPerformed(ActionEvent e) {
				my_selected_manuscript = my_manu;
				my_button_panel.getComponent(3).setEnabled(true);
				my_button_panel.getComponent(4).setEnabled(true);
		}
	}//end of CkBoxListener class
}//end of ReviewSubmitsClass


